"""
统一日志配置工具
提供项目级别的日志管理功能
"""

import logging
import os
from datetime import datetime
from pathlib import Path
from typing import Optional
import sys
import threading
import time


class DailyRotatingFileHandler(logging.FileHandler):
    """
    自动按日期轮转的文件处理器
    每天午夜自动切换到新的日志文件
    """

    def __init__(self, log_dir: Path, log_name: str, encoding='utf-8'):
        self.log_dir = log_dir
        self.log_name = log_name
        self.encoding = encoding
        self.current_date = datetime.now().strftime('%Y%m%d')

        # 确保日志目录存在
        self.log_dir.mkdir(exist_ok=True)

        # 初始化文件路径
        self.current_file_path = self._get_current_file_path()

        # 调用父类初始化
        super().__init__(self.current_file_path, encoding=encoding)

        # 线程锁，确保线程安全
        self._lock = threading.Lock()

    def _get_current_file_path(self) -> str:
        """获取当前日期的日志文件路径"""
        return str(self.log_dir / f"{self.log_name}_{self.current_date}.log")

    def _should_rotate(self) -> bool:
        """检查是否需要轮转（日期是否变化）"""
        current_date = datetime.now().strftime('%Y%m%d')
        return current_date != self.current_date

    def emit(self, record):
        """
        重写emit方法，在写入日志前检查是否需要轮转
        """
        with self._lock:
            if self._should_rotate():
                self._rotate()
            super().emit(record)

    def _rotate(self):
        """执行日志轮转"""
        try:
            # 关闭当前文件
            if self.stream:
                self.stream.close()
                self.stream = None

            # 更新日期和文件路径
            self.current_date = datetime.now().strftime('%Y%m%d')
            new_file_path = self._get_current_file_path()

            # 更新文件路径
            self.baseFilename = new_file_path

            # 重新打开新文件
            self.stream = self._open()

        except Exception as e:
            # 轮转失败时记录错误，但不影响日志记录
            print(f"日志轮转失败: {e}", file=sys.stderr)


class LoggerManager:
    """日志管理器"""
    
    _loggers = {}  # 缓存已创建的日志器
    
    @classmethod
    def get_logger(cls, name: str, log_file: Optional[str] = None, level: int = logging.INFO) -> logging.Logger:
        """
        获取或创建日志器
        
        Args:
            name: 日志器名称
            log_file: 日志文件名（不包含路径和扩展名）
            level: 日志级别
            
        Returns:
            配置好的日志器
        """
        # 如果已存在，直接返回
        if name in cls._loggers:
            return cls._loggers[name]
        
        # 创建新的日志器
        logger = cls._create_logger(name, log_file, level)
        cls._loggers[name] = logger
        return logger
    
    @classmethod
    def _create_logger(cls, name: str, log_file: Optional[str], level: int) -> logging.Logger:
        """创建新的日志器"""
        # 创建logs目录
        log_dir = Path("logs")
        log_dir.mkdir(exist_ok=True)
        
        # 创建日志器
        logger = logging.getLogger(name)
        logger.setLevel(level)
        
        # 清除已有的处理器（避免重复）
        logger.handlers.clear()
        
        # 文件处理器（支持自动日期轮转）
        if log_file:
            file_handler = DailyRotatingFileHandler(log_dir, log_file)
            file_handler.setLevel(level)

            # 文件日志格式（详细）
            file_formatter = logging.Formatter(
                '%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S'
            )
            file_handler.setFormatter(file_formatter)
            logger.addHandler(file_handler)
        
        # 控制台处理器
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(level)
        
        # 控制台日志格式（简洁）
        console_formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            datefmt='%H:%M:%S'
        )
        console_handler.setFormatter(console_formatter)
        logger.addHandler(console_handler)
        
        # 防止日志向上传播（避免重复输出）
        logger.propagate = False
        
        return logger
    
    @classmethod
    def setup_project_loggers(cls):
        """设置项目常用的日志器"""
        # 监控任务日志
        cls.get_logger("monitor", "monitor", logging.INFO)
        
        # API请求日志
        cls.get_logger("api", "api", logging.INFO)
        
        # 数据库操作日志
        cls.get_logger("database", "database", logging.WARNING)
        
        # 通知服务日志
        cls.get_logger("notification", "notification", logging.INFO)
        
        # Celery任务日志
        cls.get_logger("celery", "celery", logging.INFO)
        
        # 错误日志
        cls.get_logger("error", "error", logging.ERROR)


# 便捷函数
def get_logger(name: str, log_file: Optional[str] = None, level: int = logging.INFO) -> logging.Logger:
    """获取日志器的便捷函数"""
    return LoggerManager.get_logger(name, log_file, level)


def get_monitor_logger() -> logging.Logger:
    """获取监控任务专用日志器"""
    return LoggerManager.get_logger("monitor", "monitor", logging.DEBUG)


def get_api_logger() -> logging.Logger:
    """获取API专用日志器"""
    return LoggerManager.get_logger("api", "api", logging.INFO)


def get_notification_logger() -> logging.Logger:
    """获取通知服务专用日志器"""
    return LoggerManager.get_logger("notification", "notification", logging.INFO)


def get_celery_logger() -> logging.Logger:
    """获取Celery任务专用日志器"""
    return LoggerManager.get_logger("celery", "celery", logging.INFO)


def get_error_logger() -> logging.Logger:
    """获取错误专用日志器"""
    return LoggerManager.get_logger("error", "error", logging.ERROR)


# 日志装饰器
def log_function_call(logger_name: str = "default"):
    """
    函数调用日志装饰器
    
    Args:
        logger_name: 使用的日志器名称
    """
    def decorator(func):
        def wrapper(*args, **kwargs):
            logger = get_logger(logger_name)
            start_time = datetime.now()
            
            try:
                logger.info(f"🚀 开始执行 {func.__name__}")
                result = func(*args, **kwargs)
                
                end_time = datetime.now()
                duration = (end_time - start_time).total_seconds()
                logger.info(f"✅ {func.__name__} 执行成功，耗时: {duration:.2f}秒")
                
                return result
                
            except Exception as e:
                end_time = datetime.now()
                duration = (end_time - start_time).total_seconds()
                logger.error(f"❌ {func.__name__} 执行失败，耗时: {duration:.2f}秒，错误: {str(e)}")
                raise
                
        return wrapper
    return decorator


# 异步函数日志装饰器
def log_async_function_call(logger_name: str = "default"):
    """
    异步函数调用日志装饰器
    
    Args:
        logger_name: 使用的日志器名称
    """
    def decorator(func):
        async def wrapper(*args, **kwargs):
            logger = get_logger(logger_name)
            start_time = datetime.now()
            
            try:
                # logger.info(f"🚀 开始执行异步函数 {func.__name__}")
                result = await func(*args, **kwargs)
                
                end_time = datetime.now()
                duration = (end_time - start_time).total_seconds()
                logger.info(f"✅ {func.__name__} 执行成功，耗时: {duration:.2f}秒\n")
                
                return result
                
            except Exception as e:
                end_time = datetime.now()
                duration = (end_time - start_time).total_seconds()
                logger.error(f"❌ {func.__name__} 执行失败，耗时: {duration:.2f}秒，错误: {str(e)}")
                raise
                
        return wrapper
    return decorator


# 初始化项目日志器
LoggerManager.setup_project_loggers()
